-
Notifications
You must be signed in to change notification settings - Fork 3
Mac Catalyst Support #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
OK so command I'm testing locally w/ now (the cflags and ldflags don't worry they are my own directories w/ unpacked deps packages This is just for my own benefit. |
|
A way more involved set of changes is required; Mac Catalyst is versioned. |
|
Need logic to get the MACOS version for this -- currently we have ios deployment target: |
|
OK just destroyed the iOS testbed -- Mac Catalyst has a sort of different process to do stuff (not using simulators, diff ways to codesign etc) and I'm not that familiar and will investigate later. |
|
More stuff also needs to be modified w.r.t. versioned structure (but embedded only) for Mac Catalyst. |
|
Just pushed 2 nonworking commits on the versioned structure for mac catalyst but I have absolutely no clue right now... so I need to dig in a bit Also apologize for the large amounts of small comments. |
50c666f to
0dbdbcd
Compare
|
This branch has now diverged pretty far from the current state of In my experimentation, the build completes, but testing isn't a simple process. The testbed shouldn't be needed, as there's no need to start a simulator... but |
|
Framework structure is sort of complicated right now, there's probably no
need for the unix tools (unless someone wants a repl interface to
experiment w/ stuff on MacCatalyst, which is doable), and it has to be
relocatable (I mean technically you could have a Catalyst Python install
but my gut feeling is that it's not going to be that useful), so we need to
come up with something. My latest commit on that PR has singled out the Mac
Catalyst case in the framework install targets section of the configure.ac.
Go ahead and force push, but please reply with a commit hash of the
latest commit I have for backup. Definitely need to sort out the RPATH
stuff.
Anyway this is further away from merging than I thought when I first pulled
the pr from @asavva-2016.
…On Thu, Apr 24, 2025 at 11:23 PM Russell Keith-Magee < ***@***.***> wrote:
*freakboy3742* left a comment (freakboy3742/cpython#8)
<#8 (comment)>
This branch has now diverged pretty far from the current state of
3.14-patched; I've got all these changes collapsed into a single commit
if you'd like me to force-push an update to this branch.
In my experimentation, the build *completes*, but testing isn't a simple
process. The testbed shouldn't be needed, as there's no need to start a
simulator... but python.exe doesn't work either, because of RPATH-based
framework linking issues.
—
Reply to this email directly, view it on GitHub
<#8 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BRODAIZOBPCWLUC6NSO76B323G2EJAVCNFSM6AAAAAB3XTYCZCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQMRZGM2DAMZSGA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
|
OK just finished force-pushing -- added some new changes. |
|
Right now we have |
|
OK that is fixed and now this builds! rpath needs to be fixed definitely -- but I think we should start the review process. Remarks:
Overall I'm ending my day now but will make this ready for review so you might leave some additional remarks, even though it'll probably take at least 1-2 weeks on my end to get this merged, because I have school mon-fri and (just like you, sorry for not respecting that and the repeated pings) spend time w/ family (aka. mom dad and sibling(s) and those only) on sat and sun, so I might only have 1h at worst per day. |
|
Oh I'm really sorry but forgot to add
Also that said I'll be waking up very early tomorrow so like if you have urgent questions you can ask 6:20 pm in Perth, Australia (it's 5:20am here, but I have some stuff at 5:30am which I won't disclose). |
So - it's very difficult to review something that doesn't actually do anything yet. I can pick on cosmetic stuff (the indentation in the configure.ac is the biggest thing that stands out); but unless I can start an interpreter or run the test suite... it doesn't work yet. There's nothing to meaningfully review. This PR doesn't contain a testbed project; and as I said yesterday, when I run |
|
@freakboy3742 Thanks for organizing everything in the latest PR but afraid would have to revert some changes in the configure.ac -- anyway is a separate testbed acceptable? Or would you prefer it to be one? The latter would require some stuff and the glue scripts to be re-written. |
|
Will bundle a testbed soon but in the meantime a humongous amount of tests are failing on my end. |
e0adfdb to
dfc5b97
Compare
I'm not clear why you've reverted the configure.ac changes though. Why does MacCatalyst require a versioned framework? A versioned framework is required on macOS because it's installed in As for the testbed; I've been considering whether the |
|
Also - as there have been changes to the visionOS patch, this PR now needs to be updated; when you do, you need to use a rebase, not a merge commit. The "patch tree" approach to managing the |
|
@freakboy3742 Done |
|
There's no way AFAIK to obtain the macOS version from the Mac Catalyst verison, the former of which is actually requried in our plist, so I provided the correct value for the default version and added |
|
I just killed the MacCatalyst testbed and merged with iOS testbed. Let me know what you think -- b/c this is usually what they do when they build actual apps. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not clear why you've reverted the configure.ac changes though. Why does MacCatalyst require a versioned framework? A versioned framework is required on macOS because it's installed in
/Library; that won't be the case here.macOS distribution requires versioned framework AFAIK; see, for example, the Frameworks folder of LyX, a WYSIWYM LaTeX editor, and things like QtCore.framework is versioned:
I'm not arguing that you can't use a versioned framework - I'm asking if we must use a versioned framework.
I just killed the MacCatalyst testbed and merged with iOS testbed. Let me know what you think -- b/c this is usually what they do when they build actual apps.
Some notes inline; keep in mind that one of the primary goals here is that this is a patch on top of cpython, so changes must be kept to a minimium. Even "minor reorganisations" are a problem because they won't merge/rebase cleanly.
There's no way AFAIK to obtain the macOS version from the Mac Catalyst verison, the former of which is actually requried in our plist, so I provided the correct value for the default version and added
--with-catalyst-macos-versionto pass in the macOS version.
Why is the macOS version needed? macOS version matters when it's a gateway for features... but if you're on Catalyst, the macOS version isn't the gateway being used - it's the iOS version.
|
Turns out it was caused by me, myself. https://en.wikipedia.org/wiki/Memory_leak#Pseudocode is pretty similar, not sure if this is it, will retest |
|
Yes!!! For the first time in forever, I got a clean testbed run. Requesting a review in GitHub again, but the existing things I have not resolved are still pending reply. Thank you for your extremely nontrivial assistance on this patch. |
|
FYI - I likely won't get a chance to look at this for a couple of days; PyCon US sprints for the next couple of days will keep me fairly well occupied. |
dfc5b97 to
7926253
Compare
|
@freakboy3742 Don't believe the force push is correct... will need to drop the tvOS, watchOS + visionOS commits. EDIT or is this intentional to combine into 1 commit? EDIT nevermind it's me who need to rebase... misread branch name, sorry |
|
Done. Really sorry for accientally misreading the branch name in the last comment. |
…on't use `simctl --set testing` (pythonGH-135102) (python#135113) On a fresh Xcode install (including some CI provider configurations), there is no pre-existing testing set that can be used to identify simulator models. Use the default device set to detect available models instead. Live testing simulators are still created in the testing set. (cherry picked from commit dba9de7) Co-authored-by: Joe Rickerby <[email protected]>
7926253 to
68b83a6
Compare
|
Aplogies for missing the latest force push. |
commit a228887 Author: John Zhou <[email protected]> Date: Sat May 17 19:53:30 2025 -0500 https://en.wikipedia.org/wiki/Memory_leak#Pseudocode commit 78eb704 Author: John Zhou <[email protected]> Date: Thu May 15 22:12:29 2025 -0500 Revert "try to build multiprocessing" This reverts commit 4e92456. commit 687916e Author: John Zhou <[email protected]> Date: Thu May 15 22:07:48 2025 -0500 try to build multiprocessing commit 02be1ef Author: John Zhou <[email protected]> Date: Thu May 15 18:31:47 2025 -0500 misc fixes commit 1ff1574 Author: John Zhou <[email protected]> Date: Thu May 15 17:14:16 2025 -0500 why do i forget to handle exceptions??? commit ff71f93 Author: John Zhou <[email protected]> Date: Thu May 15 16:54:10 2025 -0500 grumble commit 8d3f831 Author: John Zhou <[email protected]> Date: Wed May 14 20:23:37 2025 -0500 grumble commit 5d73cfc Author: John Zhou <[email protected]> Date: Wed May 14 20:17:51 2025 -0500 fix test_os commit 084a83c Author: John Zhou <[email protected]> Date: Sat May 10 21:50:13 2025 -0500 disable sandbox commit c8227e4 Author: John Zhou <[email protected]> Date: Thu May 8 22:07:42 2025 -0500 platform fix commit 00c08c3 Author: John Zhou <[email protected]> Date: Thu May 8 21:28:54 2025 -0500 fix platform on tvOS et. al. commit 63433a6 Author: John Zhou <[email protected]> Date: Mon May 5 20:57:35 2025 -0500 add a missing file commit 9930836 Author: John Zhou <[email protected]> Date: Sat May 10 07:42:54 2025 -0500 use python for build commit 1ee48cd Author: John Zhou <[email protected]> Date: Sat May 3 19:23:52 2025 -0500 install binaries commit 19e8d64 Author: John Zhou <[email protected]> Date: Sat May 3 14:39:59 2025 -0500 merge test commands commit 639bf33 Author: John Zhou <[email protected]> Date: Sat May 3 09:02:19 2025 -0500 elif commit f1b9686 Author: John Zhou <[email protected]> Date: Sat May 3 09:00:09 2025 -0500 another fix commit 7253cdd Author: John Zhou <[email protected]> Date: Sat May 3 08:53:54 2025 -0500 fix test commit ab9480e Author: John Zhou <[email protected]> Date: Fri May 2 20:54:59 2025 -0500 grumble commit 5ec2564 Author: John Zhou <[email protected]> Date: Fri May 2 20:50:18 2025 -0500 nvm that did not work commit 59e62e6 Author: John Zhou <[email protected]> Date: Fri May 2 20:34:26 2025 -0500 more fixes, also parallel commit da68fb6 Author: John Zhou <[email protected]> Date: Fri May 2 18:49:29 2025 -0500 remove irrel comment commit d662098 Author: John <[email protected]> Date: Fri May 2 18:44:00 2025 -0500 Update test_util.py commit 06e8510 Author: John <[email protected]> Date: Fri May 2 18:43:24 2025 -0500 Update test_loader.py commit daf3275 Author: John <[email protected]> Date: Fri May 2 18:42:41 2025 -0500 Update __init__.py commit aaf27df Author: John <[email protected]> Date: Fri May 2 18:41:56 2025 -0500 Update test_misc.py commit 1588275 Author: John <[email protected]> Date: Fri May 2 18:41:24 2025 -0500 Update datetimetester.py commit fc008b8 Author: John Zhou <[email protected]> Date: Fri May 2 18:44:37 2025 -0500 stuff commit da006cc Author: John Zhou <[email protected]> Date: Fri May 2 18:40:58 2025 -0500 add flag for fwork commit ad7a0e1 Author: John Zhou <[email protected]> Date: Fri May 2 18:34:53 2025 -0500 haaaands commit a29e718 Author: John Zhou <[email protected]> Date: Fri May 2 18:26:38 2025 -0500 yet another error commit 8b41226 Author: John Zhou <[email protected]> Date: Fri May 2 18:08:23 2025 -0500 outdated message commit 6c07c00 Author: John Zhou <[email protected]> Date: Thu May 1 21:49:34 2025 -0500 more fixups commit 897e182 Author: John Zhou <[email protected]> Date: Thu May 1 20:58:06 2025 -0500 another ref commit 5edde3a Author: John Zhou <[email protected]> Date: Tue Apr 29 20:12:19 2025 -0500 whitespace commit 3ece1d6 Author: John Zhou <[email protected]> Date: Tue Apr 29 18:11:42 2025 -0500 I'm not sure if multiprocessing is available... commit c47a04b Author: John Zhou <[email protected]> Date: Tue Apr 29 17:39:16 2025 -0500 enable testing stuff commit fecd3b5 Author: John Zhou <[email protected]> Date: Tue Apr 29 17:23:02 2025 -0500 support fork, fix another appleframeworkloader reference commit 834b207 Author: John Zhou <[email protected]> Date: Tue Apr 29 16:52:59 2025 -0500 detect mac catalyst in datetimetester commit 03a40b1 Author: John Zhou <[email protected]> Date: Tue Apr 29 07:47:53 2025 -0500 use sys commit 849e276 Author: John Zhou <[email protected]> Date: Tue Apr 29 07:28:55 2025 -0500 bootstrap external cleanup` commit 65e3bf8 Author: John Zhou <[email protected]> Date: Tue Apr 29 07:20:31 2025 -0500 (untested) add mac catalyst detection commit 8e008c4 Author: John Zhou <[email protected]> Date: Mon Apr 28 21:37:37 2025 -0500 minor adjustments to test script commit 3d539a4 Author: John Zhou <[email protected]> Date: Mon Apr 28 21:30:45 2025 -0500 disable lib valid + use ad hoc commit d16af17 Author: John Zhou <[email protected]> Date: Sun Apr 27 21:49:08 2025 -0500 change the regex for catalyst and add if commit 823d7b6 Author: John Zhou <[email protected]> Date: Sun Apr 27 21:43:57 2025 -0500 add missing entitlemnet commit 5604df8 Author: John Zhou <[email protected]> Date: Sun Apr 27 21:32:21 2025 -0500 whitespace commit 5f767fd Author: John Zhou <[email protected]> Date: Tue Jun 3 08:12:12 2025 -0500 glue for testbed commit e7b83ae Author: John Zhou <[email protected]> Date: Sun Apr 27 18:11:17 2025 -0500 fix plist commit de0ab4d Author: John Zhou <[email protected]> Date: Sun Apr 27 18:09:32 2025 -0500 address review commit 87482cd Author: John <[email protected]> Date: Sun Apr 27 14:53:52 2025 -0500 Delete MacCatalyst/Resources/pyconfig.h commit 2e971be Author: John Zhou <[email protected]> Date: Sun Apr 27 12:27:10 2025 -0500 plist adjustments + kill maccatalyst testbed revert changes commit 8d186e3 Author: John Zhou <[email protected]> Date: Sun Apr 27 11:40:04 2025 -0500 esac commit 1a20cd7 Author: John Zhou <[email protected]> Date: Sun Apr 27 11:38:09 2025 -0500 fixes for plist commit f00cadf Author: John Zhou <[email protected]> Date: Sun Apr 27 10:47:38 2025 -0500 git rebase cleanup commit 956cfbd Author: John Zhou <[email protected]> Date: Sat Apr 26 07:00:24 2025 -0500 Remove ignored files from tracking commit 3828ce4 Author: John Zhou <[email protected]> Date: Sat Apr 26 07:00:09 2025 -0500 remove more ios refs commit bd99ef5 Author: John Zhou <[email protected]> Date: Sat Apr 26 06:49:55 2025 -0500 testbed commit 2479a35 Author: John Zhou <[email protected]> Date: Sat Apr 26 06:11:51 2025 -0500 here more code commit b3adac4 Author: John Zhou <[email protected]> Date: Sat Apr 26 05:50:09 2025 -0500 fix commit ce636cd Author: John Zhou <[email protected]> Date: Sat Apr 26 05:47:45 2025 -0500 rpath fix w/ embedded commit e0ec373 Author: John Zhou <[email protected]> Date: Sun Apr 27 10:46:32 2025 -0500 Minor cleanups. commit 4071f1d Author: John Zhou <[email protected]> Date: Fri Apr 25 20:36:44 2025 -0500 remove useless stuff. commit 54856e3 Author: John Zhou <[email protected]> Date: Fri Apr 25 18:48:41 2025 -0500 another fix commit 97598c4 Author: John Zhou <[email protected]> Date: Fri Apr 25 18:43:42 2025 -0500 another fix commit f39ed64 Author: John Zhou <[email protected]> Date: Fri Apr 25 18:38:12 2025 -0500 more changes to configure commit 9de10c0 Author: John Zhou <[email protected]> Date: Fri Apr 25 18:30:44 2025 -0500 Add supp for mac catalyst Co-Authored-By: Andrew Savva <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FInal pieces of cleanup.
|
FYI: I've cleaned up some of the things I flagged and also cleaned up a bunch of comments. |
|
Hi @freakboy3742 , been digging through my list of old PRs and found this -- could another look be taken at this? Current state of this PR should be passing the testbed; most changes have been straightforward except for the guarded file descriptor modification on line 2513 of test_os.py -- fstat fails for guarded FDs making Python think it's open to use, so for mac catalyst (not sure if relevant on other apple platforms?) the test keeps opening new FDs (since they're sequential with the exception of some of those system-guarded ones) on a file until they become non-sequential and uses the sequential range opened to test closerange. Thanks! |
|
Apologies for the delay on reviewing this. I've been mostly deferring looking into this (and #11) because I knew that python#138176 was going to be on my todo list, and it's going to be a lot easier to land other Apple changes once that change is in place. Actually getting to the point of writing that PR took a lot longer than I was hoping... So - my current intention is to wait until that PR has landed, and then integrate these changes into that new directory (and build/testbed) structure. |
|
@freakboy3742 No worries, more of a mistake on my part flooding in new PRs when I haven't completely old ones. I won't have time to integrate testbed into new directory structure though, so if your schedule's also pretty tight we either omit the testbed part or close this PR. Both options are fine with me. |
68b83a6 to
0b8aaa9
Compare
|
Alright. I'm closing this PR since I no longer have time to work on it. I was keeping it open because there weren't any structural changes upstream so I figured someone would just review it, however it seems that I've been starting too much new stuff and has now ran out of time to review the (very good) upstream structural changes.. Diff from 68b83a6 (before upstream structural changesdiff --git a/.gitignore b/.gitignore
index 3893a91e771..4c5221f4f62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,6 +82,7 @@ iOS/testbed/Python.xcframework/ios-*/Python.framework
iOS/testbed/iOSTestbed.xcodeproj/project.xcworkspace
iOS/testbed/iOSTestbed.xcodeproj/xcuserdata
iOS/testbed/iOSTestbed.xcodeproj/xcshareddata
+MacCatalyst/Resources/Info.plist
visionOS/testbed/Python.xcframework/xros-*/bin
visionOS/testbed/Python.xcframework/xros-*/include
visionOS/testbed/Python.xcframework/xros-*/lib
diff --git a/Lib/_ios_support.py b/Lib/_ios_support.py
index 20467a7c2bc..deefacaf8c5 100644
--- a/Lib/_ios_support.py
+++ b/Lib/_ios_support.py
@@ -25,6 +25,7 @@
def get_platform_ios():
# Determine if this is a simulator using the multiarch value
is_simulator = sys.implementation._multiarch.endswith("simulator")
+ is_catalyst = sys.implementation._multiarch.endswith("macabi")
# We can't use ctypes; abort
if not objc:
@@ -68,4 +69,4 @@ def get_platform_ios():
release = objc.objc_msgSend(device_systemVersion, SEL_UTF8String).decode()
model = objc.objc_msgSend(device_model, SEL_UTF8String).decode()
- return system, release, model, is_simulator
+ return system, release, model, is_simulator, is_catalyst
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index d8a6f28edba..dfab36488f6 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -1535,7 +1535,8 @@ def _get_supported_file_loaders():
"""
extension_loaders = []
if hasattr(_imp, 'create_dynamic'):
- if sys.platform in {"ios", "tvos", "watchos", "visionos"}:
+ # AppleFrameworkLoader is unessaccary on Mac Catalyst because Mac Catalyst allows "raw" dylib files.
+ if sys.platform in {"ios", "tvos", "watchos", "visionos"} and not sys.implementation._multiarch.endswith("macabi"):
extension_loaders = [(AppleFrameworkLoader, [
suffix.replace(".so", ".fwork")
for suffix in _imp.extension_suffixes()
diff --git a/Lib/platform.py b/Lib/platform.py
index cad919bc0c4..37dd6ce7bf1 100644
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -508,11 +508,11 @@ def mac_ver(release='', versioninfo=('', '', ''), machine=''):
# A namedtuple for iOS version information.
IOSVersionInfo = collections.namedtuple(
"IOSVersionInfo",
- ["system", "release", "model", "is_simulator"]
+ ["system", "release", "model", "is_simulator", "is_catalyst"]
)
-def ios_ver(system="", release="", model="", is_simulator=False):
+def ios_ver(system="", release="", model="", is_simulator=False, is_catalyst=False):
"""Get iOS version information, and return it as a namedtuple:
(system, release, model, is_simulator).
@@ -525,7 +525,7 @@ def ios_ver(system="", release="", model="", is_simulator=False):
if result is not None:
return IOSVersionInfo(*result)
- return IOSVersionInfo(system, release, model, is_simulator)
+ return IOSVersionInfo(system, release, model, is_simulator, is_catalyst)
# A namedtuple for tvOS version information.
@@ -547,6 +547,7 @@ def tvos_ver(system="", release="", model="", is_simulator=False):
import _ios_support
result = _ios_support.get_platform_ios()
if result is not None:
+ result = result[:-1] # ignore the Catalyst flag
return TVOSVersionInfo(*result)
return TVOSVersionInfo(system, release, model, is_simulator)
@@ -571,6 +572,7 @@ def watchos_ver(system="", release="", model="", is_simulator=False):
import _ios_support
result = _ios_support.get_platform_ios()
if result is not None:
+ result = result[:-1] # ignore the Catalyst flag
return WatchOSVersionInfo(*result)
return WatchOSVersionInfo(system, release, model, is_simulator)
@@ -595,6 +597,7 @@ def visionos_ver(system="", release="", model="", is_simulator=False):
import _ios_support
result = _ios_support.get_platform_ios()
if result is not None:
+ result = result[:-1] # ignore the Catalyst flag
return VisionOSVersionInfo(*result)
return VisionOSVersionInfo(system, release, model, is_simulator)
@@ -963,12 +966,12 @@ def get_OpenVMS():
csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
return 'Alpha' if cpu_number >= 128 else 'VAX'
- # On the iOS/tvOS/watchOS/visionOS simulator, os.uname returns the architecture as
- # uname.machine. On device it returns the model name for some reason; but
- # there's only one CPU architecture for devices, so we know the right
- # answer.
+ # On the iOS/tvOS/watchOS/visionOS simulator and Mac Catalyst, os.uname returns
+ # the architecture as uname.machine. On device it returns the model name for
+ # some reason; but there's only one CPU architecture for devices, so we know the
+ # right answer.
def get_ios():
- if sys.implementation._multiarch.endswith("simulator"):
+ if sys.implementation._multiarch.endswith("simulator") or sys.implementation._multiarch.endswith("macabi"):
return os.uname().machine
return 'arm64'
@@ -1148,7 +1151,7 @@ def uname():
# Normalize responses on Apple mobile platforms
if sys.platform == 'ios':
- system, release, _, _ = ios_ver()
+ system, release, _, _, _ = ios_ver()
if sys.platform == 'tvos':
system, release, _, _ = tvos_ver()
if sys.platform == 'watchos':
@@ -1441,9 +1444,9 @@ def platform(aliased=False, terse=False):
system, release, version = system_alias(system, release, version)
if system == 'Darwin':
- # macOS and iOS both report as a "Darwin" kernel
+ # All Apple Platforms report as a "Darwin" kernel
if sys.platform == "ios":
- system, release, _, _ = ios_ver()
+ system, release, _, _, _ = ios_ver()
elif sys.platform == "tvos":
system, release, _, _ = tvos_ver()
elif sys.platform == "watchos":
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 03896a234bf..9b3f9f612e9 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -75,7 +75,10 @@
_mswindows = True
# some platforms do not support subprocesses
-_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos", "visionos"}
+_can_fork_exec = (
+ sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos", "visionos"}
+ or sys.implementation._multiarch.endswith("macabi") # Mac Catalyst
+)
if _mswindows:
import _winapi
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 8594f92c097..7eecf926082 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -7159,9 +7159,9 @@ def test_datetime_from_timestamp(self):
self.assertEqual(dt_orig, dt_rt)
def test_type_check_in_subinterp(self):
- # Apple mobile platforms require the use of the custom framework loader,
- # not the ExtensionFileLoader.
- if support.is_apple_mobile:
+ # Apple mobile platforms except Mac Catalyst require the use of the
+ # custom framework loader, not the ExtensionFileLoader.
+ if support.needs_apple_fworks:
extension_loader = "AppleFrameworkLoader"
else:
extension_loader = "ExtensionFileLoader"
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 32243a49e7a..4f027912b0a 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -46,6 +46,7 @@
# sys
"MS_WINDOWS", "is_jython", "is_android", "is_emscripten", "is_wasi",
"is_apple_mobile", "check_impl_detail", "unix_shell", "setswitchinterval",
+ "is_mac_catalyst", "needs_apple_fworks",
# os
"get_pagesize",
# network
@@ -576,6 +577,8 @@ def skip_wasi_stack_overflow():
is_apple_mobile = sys.platform in {"ios", "tvos", "watchos", "visionos"}
is_apple = is_apple_mobile or sys.platform == "darwin"
+is_mac_catalyst = sys.implementation._multiarch.endswith("macabi")
+needs_apple_fworks = is_apple_mobile and not is_mac_catalyst
has_fork_support = hasattr(os, "fork") and not (
# WASM and Apple mobile platforms do not support subprocesses.
@@ -586,6 +589,9 @@ def skip_wasi_stack_overflow():
# Although Android supports fork, it's unsafe to call it from Python because
# all Android apps are multi-threaded.
or is_android
+
+ # Mac Catalyst supports subprocesses.
+ and not is_mac_catalyst
)
def requires_fork():
@@ -601,6 +607,9 @@ def requires_fork():
# practice (see PEP 738). And most of the tests that use them are calling
# sys.executable, which won't work when Python is embedded in an Android app.
or is_android
+
+ # Mac Catalyst supports subprocesses.
+ and not is_mac_catalyst
)
def requires_subprocess():
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index f74694a7a74..5ad6f4d4ff1 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -1920,7 +1920,7 @@ def test_module_state_shared_in_global(self):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if support.is_apple_mobile:
+ if support.needs_apple_fworks:
loader = "AppleFrameworkLoader"
else:
loader = "ExtensionFileLoader"
@@ -2604,7 +2604,7 @@ def setUp(self):
origin = importlib.util.find_spec('_testmultiphase').origin
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if support.is_apple_mobile:
+ if support.needs_apple_fworks:
loader = importlib.machinery.AppleFrameworkLoader(fullname, origin)
else:
loader = importlib.machinery.ExtensionFileLoader(fullname, origin)
diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py
index 6e34094c5aa..87a81fdecfd 100644
--- a/Lib/test/test_import/__init__.py
+++ b/Lib/test/test_import/__init__.py
@@ -33,7 +33,7 @@
swap_attr,
swap_item,
cpython_only,
- is_apple_mobile,
+ needs_apple_fworks,
is_emscripten,
is_wasi,
run_in_subinterp,
@@ -111,7 +111,7 @@ def require_builtin(module, *, skip=False):
def require_extension(module, *, skip=False):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
_require_loader(module, AppleFrameworkLoader, skip)
else:
_require_loader(module, ExtensionFileLoader, skip)
@@ -126,7 +126,7 @@ def require_pure_python(module, *, skip=False):
def create_extension_loader(modname, filename):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
return AppleFrameworkLoader(modname, filename)
else:
return ExtensionFileLoader(modname, filename)
@@ -2217,7 +2217,7 @@ def import_script(self, name, fd, filename=None, check_override=None):
if filename:
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
loader = "AppleFrameworkLoader"
else:
loader = "ExtensionFileLoader"
@@ -2692,7 +2692,7 @@ def setUpClass(cls):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader, and we need to differentiate between the
# spec.origin and the original file location.
- if is_apple_mobile:
+ if needs_apple_fworks:
assert cls.LOADER is AppleFrameworkLoader
cls.ORIGIN = spec.origin
diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py
index cdc8884d668..d1b525f6419 100644
--- a/Lib/test/test_importlib/extension/test_finder.py
+++ b/Lib/test/test_importlib/extension/test_finder.py
@@ -1,4 +1,4 @@
-from test.support import is_apple_mobile
+from test.support import needs_apple_fworks
from test.test_importlib import abc, util
machinery = util.import_importlib('importlib.machinery')
@@ -20,7 +20,7 @@ def setUp(self):
)
def find_spec(self, fullname):
- if is_apple_mobile:
+ if needs_apple_fworks:
# Apple mobile platforms require a specialist loader that uses
# .fwork files as placeholders for the true `.so` files.
loaders = [
diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py
index 0dd21e079eb..efae18d4bbd 100644
--- a/Lib/test/test_importlib/extension/test_loader.py
+++ b/Lib/test/test_importlib/extension/test_loader.py
@@ -1,4 +1,4 @@
-from test.support import is_apple_mobile
+from test.support import needs_apple_fworks
from test.test_importlib import abc, util
machinery = util.import_importlib('importlib.machinery')
@@ -28,7 +28,7 @@ def setUp(self):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
self.LoaderClass = self.machinery.AppleFrameworkLoader
else:
self.LoaderClass = self.machinery.ExtensionFileLoader
@@ -110,7 +110,7 @@ def setUp(self):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
self.LoaderClass = self.machinery.AppleFrameworkLoader
else:
self.LoaderClass = self.machinery.ExtensionFileLoader
@@ -198,7 +198,7 @@ def setUp(self):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if is_apple_mobile:
+ if needs_apple_fworks:
self.LoaderClass = self.machinery.AppleFrameworkLoader
else:
self.LoaderClass = self.machinery.ExtensionFileLoader
diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py
index 5de89714eb5..0c6661791ca 100644
--- a/Lib/test/test_importlib/test_util.py
+++ b/Lib/test/test_importlib/test_util.py
@@ -714,7 +714,7 @@ def test_single_phase_init_module(self):
def test_incomplete_multi_phase_init_module(self):
# Apple extensions must be distributed as frameworks. This requires
# a specialist loader.
- if support.is_apple_mobile:
+ if support.needs_apple_fworks:
loader = "AppleFrameworkLoader"
else:
loader = "ExtensionFileLoader"
diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py
index edbe78545a2..d1f6965196f 100644
--- a/Lib/test/test_importlib/util.py
+++ b/Lib/test/test_importlib/util.py
@@ -8,7 +8,7 @@
import os.path
from test import support
from test.support import import_helper
-from test.support import is_apple_mobile
+from test.support import needs_apple_fworks
from test.support import os_helper
import unittest
import sys
@@ -48,7 +48,7 @@ def _extension_details():
for ext in machinery.EXTENSION_SUFFIXES:
# Apple mobile platforms mechanically load .so files,
# but the findable files are labelled .fwork
- if is_apple_mobile:
+ if needs_apple_fworks:
ext = ext.replace(".so", ".fwork")
filename = EXTENSIONS.name + ext
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 88b5b0e6e35..c5121fee00e 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2510,19 +2510,54 @@ def test_isatty(self):
@unittest.skipUnless(hasattr(os, 'closerange'), 'test needs os.closerange()')
def test_closerange(self):
- fd = os_helper.make_bad_fd()
- # Make sure none of the descriptors we are about to close are
- # currently valid (issue 6542).
- for i in range(10):
- try: os.fstat(fd+i)
- except OSError:
- pass
- else:
- break
- if i < 2:
- raise unittest.SkipTest(
- "Unable to acquire a range of invalid file descriptors")
- self.assertEqual(os.closerange(fd, fd + i-1), None)
+ if support.is_mac_catalyst:
+ # On Mac Catalyst and potentially other Apple platforms,
+ # somehow there's a guarded FD in the way, that has no
+ # effect on fstat. We make some random FDs first, stop
+ # once not consecutive, close all of them one by one by calling
+ # file.close(), then assert that closerange on the FDs is failing.
+ # This ensures that none of those things we're closing is
+ # guarded, if we're careful to not use code that makes guarded
+ # file descriptors between when we manually made and
+ # destroyed them and when we're attempting to invoke
+ # closerange.
+
+ copies = []
+ # Open a file for testing and get its FD
+ file = open(os_helper.TESTFN, "wb")
+ fd = file.fileno()
+ copies.append(file)
+ for i in range(1, 10):
+ file_dup = open(os_helper.TESTFN, "wb")
+ if file_dup.fileno() != fd + i:
+ file_dup.close()
+ break
+ else:
+ copies.append(file_dup)
+ # Close everything
+ for copy in copies:
+ copy.close()
+ os.unlink(os_helper.TESTFN)
+ if i < 2:
+ raise unittest.SkipTest(
+ "Unable to acquire a range of invalid file descriptors")
+
+ # Now we're left with invalid FDs. Let's go close them!
+ self.assertEqual(os.closerange(fd, fd + i-1), None)
+ else:
+ fd = os_helper.make_bad_fd()
+ # Make sure none of the descriptors we are about to close are
+ # currently valid (issue 6542).
+ for i in range(10):
+ try: os.fstat(fd+i)
+ except OSError:
+ pass
+ else:
+ break
+ if i < 2:
+ raise unittest.SkipTest(
+ "Unable to acquire a range of invalid file descriptors")
+ self.assertEqual(os.closerange(fd, fd + i-1), None)
@unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()')
def test_dup2(self):
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index 92a831a9148..2f4f221fe4f 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -488,7 +488,7 @@ def test_ios_ver(self):
# ios_ver is only fully available on iOS where ctypes is available.
if sys.platform == "ios" and _ctypes:
- system, release, model, is_simulator = result
+ system, release, model, is_simulator, is_catalyst = result
# Result is a namedtuple
self.assertEqual(result.system, system)
self.assertEqual(result.release, release)
@@ -499,6 +499,7 @@ def test_ios_ver(self):
# ios_ver(), so we check that the values are broadly what we expect.
# System is either iOS or iPadOS, depending on the test device
+ # Mac Catalyst returns iPadOS.
self.assertIn(system, {"iOS", "iPadOS"})
# Release is a numeric version specifier with at least 2 parts
@@ -511,6 +512,9 @@ def test_ios_ver(self):
# we get a model descriptor like "iPhone13,1"
if is_simulator:
self.assertIn(model, {"iPhone", "iPad"})
+ # Mac Catalyst identifies as iPad with no version.
+ elif is_catalyst:
+ self.assertEqual(model, "iPad")
else:
self.assertTrue(
(model.startswith("iPhone") or model.startswith("iPad"))
@@ -518,6 +522,10 @@ def test_ios_ver(self):
)
self.assertEqual(type(is_simulator), bool)
+
+ # Mac Catalyst platform will return iPadOS.
+ if is_catalyst:
+ self.assertEqual(system, "iPadOS")
else:
# On non-iOS platforms, calling ios_ver doesn't fail; you get
# default values
@@ -527,11 +535,12 @@ def test_ios_ver(self):
self.assertFalse(result.is_simulator)
# Check the fallback values can be overridden by arguments
- override = platform.ios_ver("Foo", "Bar", "Whiz", True)
+ override = platform.ios_ver("Foo", "Bar", "Whiz", True, True)
self.assertEqual(override.system, "Foo")
self.assertEqual(override.release, "Bar")
self.assertEqual(override.model, "Whiz")
self.assertTrue(override.is_simulator)
+ self.assertTrue(override.is_catalyst)
@unittest.skipIf(support.is_emscripten, "Does not apply to Emscripten")
def test_libc_ver(self):
diff --git a/MacCatalyst/Resources/Info.plist.in b/MacCatalyst/Resources/Info.plist.in
new file mode 100644
index 00000000000..80b5664508e
--- /dev/null
+++ b/MacCatalyst/Resources/Info.plist.in
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>Python</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Python Runtime and Library</string>
+ <key>CFBundleIdentifier</key>
+ <string>@PYTHONFRAMEWORKIDENTIFIER@</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Python</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>%VERSION%</string>
+ <key>CFBundleLongVersionString</key>
+ <string>%VERSION%, (c) 2001-2024 Python Software Foundation.</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>%VERSION%</string>
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>MacOSX</string>
+ </array>
+ <key>LSMinimumSystemVersion</key>
+ <string>@CATALYST_MACOS_VERSION@</string>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>2</integer>
+ </array>
+</dict>
+</plist>
diff --git a/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-ar b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-ar
new file mode 100755
index 00000000000..1e31b940c23
--- /dev/null
+++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} ar "$@"
diff --git a/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang
new file mode 100755
index 00000000000..6845b5d1b20
--- /dev/null
+++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi "$@"
diff --git a/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang++
new file mode 100755
index 00000000000..779c3166268
--- /dev/null
+++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi "$@"
diff --git a/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-cpp b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-cpp
new file mode 100755
index 00000000000..01ff56a0f0e
--- /dev/null
+++ b/MacCatalyst/Resources/bin/arm64-apple-ios-macabi-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi -E "$@"
diff --git a/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-ar b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-ar
new file mode 100755
index 00000000000..1e31b940c23
--- /dev/null
+++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-ar
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} ar "$@"
diff --git a/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang
new file mode 100755
index 00000000000..a3170bb1f15
--- /dev/null
+++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi "$@"
diff --git a/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang++
new file mode 100755
index 00000000000..d3161b335e1
--- /dev/null
+++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-clang++
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang++ -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi "$@"
diff --git a/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-cpp b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-cpp
new file mode 100755
index 00000000000..7e3e9124123
--- /dev/null
+++ b/MacCatalyst/Resources/bin/x86_64-apple-ios-macabi-cpp
@@ -0,0 +1,2 @@
+#!/bin/sh
+xcrun --sdk macosx${MACOSX_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-macabi -E "$@"
diff --git a/MacCatalyst/Resources/pyconfig.h b/MacCatalyst/Resources/pyconfig.h
new file mode 100644
index 00000000000..4acff2c6051
--- /dev/null
+++ b/MacCatalyst/Resources/pyconfig.h
@@ -0,0 +1,7 @@
+#ifdef __arm64__
+#include "pyconfig-arm64.h"
+#endif
+
+#ifdef __x86_64__
+#include "pyconfig-x86_64.h"
+#endif
diff --git a/Makefile.pre.in b/Makefile.pre.in
index e436b2efb8e..d8df7de3102 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -2277,10 +2277,6 @@ testios:
echo "Cannot run the iOS testbed for a non-iOS build."; \
exit 1;\
fi
- @if test "$(findstring -iphonesimulator,$(MULTIARCH))" != "-iphonesimulator"; then \
- echo "Cannot run the iOS testbed for non-simulator builds."; \
- exit 1;\
- fi
@if test $(PYTHONFRAMEWORK) != "Python"; then \
echo "Cannot run the iOS testbed with a non-default framework name."; \
exit 1;\
@@ -2290,11 +2286,18 @@ testios:
exit 1;\
fi
- # Clone the testbed project into the XCFOLDER-iOS
- $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)"
-
- # Run the testbed project
- $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" run --verbose -- test -uall --single-process --rerun -W
+ @if test "$(findstring -iphonesimulator,$(MULTIARCH))" != "-iphonesimulator"; then \
+ if test "$(findstring -macabi,$(MULTIARCH))" != "-macabi"; then \
+ echo "Cannot run the iOS testbed for device builds."; \
+ exit 1;\
+ else \
+ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed --catalyst clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)"; \
+ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" --catalyst run --verbose -- test -uall --single-process --rerun -W; \
+ fi \
+ else \
+ $(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER-iOS)"; \
+ $(PYTHON_FOR_BUILD) "$(XCFOLDER-iOS)" run --verbose -- test -uall --single-process --rerun -W; \
+ fi
# Run the test suite on the visionOS simulator. Must be run on a macOS machine with
# a full Xcode install that has an Apple Vision Pro simulator available.
@@ -3013,7 +3016,7 @@ frameworkinstallversionedstructure: $(LDLIBRARY)
fi; \
done
$(LN) -fsn include/python$(LDVERSION) $(DESTDIR)$(prefix)/Headers
- sed 's/%VERSION%/'"`$(RUNSHARED) ./$(BUILDPYTHON) -c 'import platform; print(platform.python_version())'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(prefix)/Resources/Info.plist
+ sed 's/%VERSION%/'"`$(RUNSHARED) ./$(PYTHON_FOR_BUILD) -c 'import platform; print(platform.python_version())'`"'/g' < $(RESSRCDIR)/Info.plist > $(DESTDIR)$(prefix)/Resources/Info.plist
$(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current
$(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK)
$(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers
@@ -3041,6 +3044,14 @@ frameworkinstallunversionedstructure: $(LDLIBRARY)
$(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \
done
+# Stub compilation assistance binaries are installed separately on Mac Catalyst.
+.PHONY: frameworkinstallcatalyststubs
+frameworkinstallcatalyststubs: $(LDLIBRARY)
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(BINDIR)
+ for file in $(srcdir)/$(RESSRCDIR)/bin/* ; do \
+ $(INSTALL) -m $(EXEMODE) $$file $(DESTDIR)$(BINDIR); \
+ done
+
# This installs Mac/Lib into the framework
# Install a number of symlinks to keep software that expects a normal unix
# install (which includes python-config) happy.
diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c
index 6c1863c943b..ba634ae1699 100644
--- a/Misc/platform_triplet.c
+++ b/Misc/platform_triplet.c
@@ -254,6 +254,12 @@ PLATFORM_TRIPLET=x86_64-iphonesimulator
# else
PLATFORM_TRIPLET=arm64-iphonesimulator
# endif
+# elif defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST
+# if __x86_64__
+PLATFORM_TRIPLET=x86_64-iphoneos-macabi
+# else
+PLATFORM_TRIPLET=arm64-iphoneos-macabi
+# endif
# else
PLATFORM_TRIPLET=arm64-iphoneos
# endif
diff --git a/config.sub b/config.sub
index 49febd56a37..6efa3fbf821 100755
--- a/config.sub
+++ b/config.sub
@@ -1769,7 +1769,7 @@ case $os in
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* | cos* | mbr* | ironclad* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* | macabi)
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1869,6 +1869,8 @@ case $kernel-$os-$obj in
;;
ios*-simulator- | tvos*-simulator- | watchos*-simulator- | xros*-simulator-)
;;
+ ios*-macabi- )
+ ;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
# can be paired with an machine code file format
diff --git a/configure b/configure
index 7c93d36e717..5710b745618 100755
--- a/configure
+++ b/configure
@@ -982,6 +982,7 @@ LDFLAGS
CFLAGS
CC
HAS_XCRUN
+CATALYST_MACOS_VERSION
EXPORT_XROS_DEPLOYMENT_TARGET
XROS_DEPLOYMENT_TARGET
WATCHOS_DEPLOYMENT_TARGET
@@ -1089,6 +1090,7 @@ with_universal_archs
with_framework_name
enable_framework
with_app_store_compliance
+with_catalyst_macos_version
enable_wasm_dynamic_linking
enable_wasm_pthreads
with_suffix
@@ -1878,6 +1880,9 @@ Optional Packages:
Enable any patches required for compiliance with app
stores. Optional PATCH-FILE specifies the custom
patch to apply.
+ --with-catalyst-macos-version=VER
+ The minimum macOS version a Catalyst build can run
+ on (only valid for *-apple-ios*-macabi targets)
--with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty,
yes is mapped to '.exe')
--without-static-libpython
@@ -4222,9 +4227,12 @@ fi
# configure will fail.
if test -z "$AR"; then
case "$host" in
+ x86_64-apple-ios*-macabi) AR=x86_64-apple-ios-macabi-ar ;;
+ aarch64-apple-ios*-macabi) AR=arm64-apple-ios-macabi-ar ;;
+
+ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;;
aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;;
aarch64-apple-ios*) AR=arm64-apple-ios-ar ;;
- x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;;
aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;;
aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;;
@@ -4241,9 +4249,12 @@ if test -z "$AR"; then
fi
if test -z "$CC"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CC=x86_64-apple-ios-macabi-clang ;;
+ aarch64-apple-ios*-macabi) CC=arm64-apple-ios-macabi-clang ;;
+
+ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;;
aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;;
aarch64-apple-ios*) CC=arm64-apple-ios-clang ;;
- x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;;
aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;;
aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;;
@@ -4260,9 +4271,12 @@ if test -z "$CC"; then
fi
if test -z "$CPP"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CPP=x86_64-apple-ios-macabi-cpp ;;
+ aarch64-apple-ios*-macabi) CPP=arm64-apple-ios-macabi-cpp ;;
+
+ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;;
aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;;
aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;;
- x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;;
aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;;
aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;;
@@ -4279,9 +4293,12 @@ if test -z "$CPP"; then
fi
if test -z "$CXX"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CXX=x86_64-apple-ios-macabi-clang++ ;;
+ aarch64-apple-ios*-macabi) CXX=arm64-apple-ios-macabi-clang++ ;;
+
+ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;;
aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;;
aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;;
- x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;;
aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;;
aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;;
@@ -4524,19 +4541,34 @@ then :
;;
iOS) :
- FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
- FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
- FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
- FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
- FRAMEWORKPYTHONW=
- INSTALLTARGETS="libinstall inclinstall sharedinstall"
-
- prefix=$PYTHONFRAMEWORKPREFIX
- PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
- RESSRCDIR=iOS/Resources
-
- ac_config_files="$ac_config_files iOS/Resources/Info.plist"
+ case $(echo $host | cut -d '-' -f4) in
+ macabi)
+ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs "
+ FRAMEWORKINSTALLLAST=""
+ FRAMEWORKALTINSTALLLAST=""
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION"
+ RESSRCDIR=MacCatalyst/Resources
+ ac_config_files="$ac_config_files MacCatalyst/Resources/Info.plist"
+
+ ;;
+ *)
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=iOS/Resources
+ ac_config_files="$ac_config_files iOS/Resources/Info.plist"
+ ;;
+ esac
;;
tvOS) :
FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
@@ -4688,6 +4720,34 @@ fi
+
+
+# Check whether --with-catalyst-macos-version was given.
+if test ${with_catalyst_macos_version+y}
+then :
+ withval=$with_catalyst_macos_version; case "$host" in
+ *-apple-ios*-macabi)
+ CATALYST_MACOS_VERSION="$withval"
+ ;;
+ *)
+ as_fn_error $? "--with-catalyst-macos-version is only valid when targeting Mac Catalyst (*-apple-ios*-macabi)." "$LINENO" 5
+ ;;
+ esac
+
+else case e in #(
+ e) case "$host" in
+ *-apple-ios*-macabi)
+ CATALYST_MACOS_VERSION=11.2
+ ;;
+ *)
+ CATALYST_MACOS_VERSION=
+ ;;
+ esac
+
+ ;;
+esac
+fi
+
EXPORT_XROS_DEPLOYMENT_TARGET='#'
@@ -4705,6 +4765,28 @@ if test "$cross_compiling" = yes; then
*-*-cygwin*)
_host_ident=
;;
+ *-apple-ios*-macabi)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4` # should be macabi
+ _host_device=${_host_device:=os}
+
+ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking iOS deployment target" >&5
+printf %s "checking iOS deployment target... " >&6; }
+ IPHONEOS_DEPLOYMENT_TARGET=$(echo ${_host_os} | cut -c4-)
+ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=14.2} # else it returns invalid version number
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $IPHONEOS_DEPLOYMENT_TARGET" >&5
+printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphoneos-${_host_device} # platform_triplet.c uses iphoneos-macabi
+ ;;
+ *)
+ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphoneos-${_host_device}
+ ;;
+ esac
+ ;;
*-apple-ios*)
_host_os=`echo $host | cut -d '-' -f3`
_host_device=`echo $host | cut -d '-' -f4`
@@ -4969,6 +5051,10 @@ EXPORT_MACOSX_DEPLOYMENT_TARGET='#'
# XROS_DEPLOYMENT_TARGET should get exported
+# The minimum macOS version that a Mac Catalyst build can run on.
+
+
+
# checks for alternative programs
# compiler flags are generated in two sets, BASECFLAGS and OPT. OPT is just
@@ -7459,6 +7545,10 @@ case $host/$ac_cv_cc_name in #(
PY_SUPPORT_TIER=3 ;; #(
x86_64-*-freebsd*/clang) :
PY_SUPPORT_TIER=3 ;; #(
+ aarch64-apple-ios*-macabi/clang) :
+ PY_SUPPORT_TIER=3 ;; #(
+ x86_64-apple-ios*-macabi/clang) :
+ PY_SUPPORT_TIER=3 ;; #(
aarch64-apple-ios*-simulator/clang) :
PY_SUPPORT_TIER=3 ;; #(
aarch64-apple-ios*/clang) :
@@ -31344,6 +31434,13 @@ case $ac_sys_system in #(
;; #(
iOS|tvOS|watchOS|visionOS) :
+ case "$_host_device" in
+ macabi) ;;
+ *)
+
+ py_cv_module__posixsubprocess=n/a
+ ;;
+ esac
py_cv_module__curses=n/a
@@ -31351,7 +31448,6 @@ case $ac_sys_system in #(
py_cv_module__gdbm=n/a
py_cv_module__multiprocessing=n/a
py_cv_module__posixshmem=n/a
- py_cv_module__posixsubprocess=n/a
py_cv_module__scproxy=n/a
py_cv_module__tkinter=n/a
py_cv_module_grp=n/a
@@ -35503,6 +35599,7 @@ do
"Mac/PythonLauncher/Makefile") CONFIG_FILES="$CONFIG_FILES Mac/PythonLauncher/Makefile" ;;
"Mac/Resources/framework/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/framework/Info.plist" ;;
"Mac/Resources/app/Info.plist") CONFIG_FILES="$CONFIG_FILES Mac/Resources/app/Info.plist" ;;
+ "MacCatalyst/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES MacCatalyst/Resources/Info.plist" ;;
"iOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES iOS/Resources/Info.plist" ;;
"tvOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES tvOS/Resources/Info.plist" ;;
"watchOS/Resources/Info.plist") CONFIG_FILES="$CONFIG_FILES watchOS/Resources/Info.plist" ;;
diff --git a/configure.ac b/configure.ac
index 7ab0609bf8a..1c47cbef67d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,9 +426,12 @@ AC_SUBST([host_exec_prefix])
# configure will fail.
if test -z "$AR"; then
case "$host" in
+ x86_64-apple-ios*-macabi) AR=x86_64-apple-ios-macabi-ar ;;
+ aarch64-apple-ios*-macabi) AR=arm64-apple-ios-macabi-ar ;;
+
+ x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;;
aarch64-apple-ios*-simulator) AR=arm64-apple-ios-simulator-ar ;;
aarch64-apple-ios*) AR=arm64-apple-ios-ar ;;
- x86_64-apple-ios*-simulator) AR=x86_64-apple-ios-simulator-ar ;;
aarch64-apple-tvos*-simulator) AR=arm64-apple-tvos-simulator-ar ;;
aarch64-apple-tvos*) AR=arm64-apple-tvos-ar ;;
@@ -445,9 +448,12 @@ if test -z "$AR"; then
fi
if test -z "$CC"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CC=x86_64-apple-ios-macabi-clang ;;
+ aarch64-apple-ios*-macabi) CC=arm64-apple-ios-macabi-clang ;;
+
+ x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;;
aarch64-apple-ios*-simulator) CC=arm64-apple-ios-simulator-clang ;;
aarch64-apple-ios*) CC=arm64-apple-ios-clang ;;
- x86_64-apple-ios*-simulator) CC=x86_64-apple-ios-simulator-clang ;;
aarch64-apple-tvos*-simulator) CC=arm64-apple-tvos-simulator-clang ;;
aarch64-apple-tvos*) CC=arm64-apple-tvos-clang ;;
@@ -464,9 +470,12 @@ if test -z "$CC"; then
fi
if test -z "$CPP"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CPP=x86_64-apple-ios-macabi-cpp ;;
+ aarch64-apple-ios*-macabi) CPP=arm64-apple-ios-macabi-cpp ;;
+
+ x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;;
aarch64-apple-ios*-simulator) CPP=arm64-apple-ios-simulator-cpp ;;
aarch64-apple-ios*) CPP=arm64-apple-ios-cpp ;;
- x86_64-apple-ios*-simulator) CPP=x86_64-apple-ios-simulator-cpp ;;
aarch64-apple-tvos*-simulator) CPP=arm64-apple-tvos-simulator-cpp ;;
aarch64-apple-tvos*) CPP=arm64-apple-tvos-cpp ;;
@@ -483,9 +492,12 @@ if test -z "$CPP"; then
fi
if test -z "$CXX"; then
case "$host" in
+ x86_64-apple-ios*-macabi) CXX=x86_64-apple-ios-macabi-clang++ ;;
+ aarch64-apple-ios*-macabi) CXX=arm64-apple-ios-macabi-clang++ ;;
+
+ x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;;
aarch64-apple-ios*-simulator) CXX=arm64-apple-ios-simulator-clang++ ;;
aarch64-apple-ios*) CXX=arm64-apple-ios-clang++ ;;
- x86_64-apple-ios*-simulator) CXX=x86_64-apple-ios-simulator-clang++ ;;
aarch64-apple-tvos*-simulator) CXX=arm64-apple-tvos-simulator-clang++ ;;
aarch64-apple-tvos*) CXX=arm64-apple-tvos-clang++ ;;
@@ -716,18 +728,32 @@ AC_ARG_ENABLE([framework],
AC_CONFIG_FILES([Mac/Resources/app/Info.plist])
;;
iOS) :
- FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
- FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
- FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
- FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
- FRAMEWORKPYTHONW=
- INSTALLTARGETS="libinstall inclinstall sharedinstall"
-
- prefix=$PYTHONFRAMEWORKPREFIX
- PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
- RESSRCDIR=iOS/Resources
-
- AC_CONFIG_FILES([iOS/Resources/Info.plist])
+ case $(echo $host | cut -d '-' -f4) in
+ macabi)
+ FRAMEWORKINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallversionedstructure frameworkinstallcatalyststubs "
+ FRAMEWORKINSTALLLAST=""
+ FRAMEWORKALTINSTALLLAST=""
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+ prefix=$PYTHONFRAMEWORKINSTALLDIR/Versions/$VERSION
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR/Versions/$VERSION"
+ RESSRCDIR=MacCatalyst/Resources
+ AC_CONFIG_FILES([MacCatalyst/Resources/Info.plist])
+ ;;
+ *)
+ FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
+ FRAMEWORKALTINSTALLFIRST="frameworkinstallunversionedstructure "
+ FRAMEWORKINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKALTINSTALLLAST="frameworkinstallmobileheaders"
+ FRAMEWORKPYTHONW=
+ INSTALLTARGETS="libinstall inclinstall sharedinstall"
+ prefix=$PYTHONFRAMEWORKPREFIX
+ PYTHONFRAMEWORKINSTALLNAMEPREFIX="@rpath/$PYTHONFRAMEWORKDIR"
+ RESSRCDIR=iOS/Resources
+ AC_CONFIG_FILES([iOS/Resources/Info.plist])
+ ;;
+ esac
;;
tvOS) :
FRAMEWORKINSTALLFIRST="frameworkinstallunversionedstructure"
@@ -863,6 +889,29 @@ AC_ARG_WITH(
])
AC_SUBST([APP_STORE_COMPLIANCE_PATCH])
+
+AC_ARG_WITH([catalyst-macos-version],
+ [AS_HELP_STRING([--with-catalyst-macos-version=VER],
+ [The minimum macOS version a Catalyst build can run on (only valid for *-apple-ios*-macabi targets)])],
+ [case "$host" in
+ *-apple-ios*-macabi)
+ CATALYST_MACOS_VERSION="$withval"
+ ;;
+ *)
+ AC_MSG_ERROR([--with-catalyst-macos-version is only valid when targeting Mac Catalyst (*-apple-ios*-macabi).])
+ ;;
+ esac
+ ],
+ [case "$host" in
+ *-apple-ios*-macabi)
+ CATALYST_MACOS_VERSION=11.2
+ ;;
+ *)
+ CATALYST_MACOS_VERSION=
+ ;;
+ esac
+ ]
+)
EXPORT_XROS_DEPLOYMENT_TARGET='#'
AC_SUBST([_PYTHON_HOST_PLATFORM])
@@ -880,6 +929,26 @@ if test "$cross_compiling" = yes; then
*-*-cygwin*)
_host_ident=
;;
+ *-apple-ios*-macabi)
+ _host_os=`echo $host | cut -d '-' -f3`
+ _host_device=`echo $host | cut -d '-' -f4` # should be macabi
+ _host_device=${_host_device:=os}
+
+ # IPHONEOS_DEPLOYMENT_TARGET is the minimum supported iOS version
+ AC_MSG_CHECKING([iOS deployment target])
+ IPHONEOS_DEPLOYMENT_TARGET=$(echo ${_host_os} | cut -c4-)
+ IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET:=14.2} # else it returns invalid version number
+ AC_MSG_RESULT([$IPHONEOS_DEPLOYMENT_TARGET])
+
+ case "$host_cpu" in
+ aarch64)
+ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-arm64-iphoneos-${_host_device} # platform_triplet.c uses iphoneos-macabi
+ ;;
+ *)
+ _host_ident=${IPHONEOS_DEPLOYMENT_TARGET}-$host_cpu-iphoneos-${_host_device}
+ ;;
+ esac
+ ;;
*-apple-ios*)
_host_os=`echo $host | cut -d '-' -f3`
_host_device=`echo $host | cut -d '-' -f4`
@@ -1129,6 +1198,10 @@ AC_SUBST([XROS_DEPLOYMENT_TARGET])
# XROS_DEPLOYMENT_TARGET should get exported
AC_SUBST([EXPORT_XROS_DEPLOYMENT_TARGET])
+# The minimum macOS version that a Mac Catalyst build can run on.
+AC_SUBST([CATALYST_MACOS_VERSION])
+
+
# checks for alternative programs
# compiler flags are generated in two sets, BASECFLAGS and OPT. OPT is just
@@ -1418,6 +1491,8 @@ AS_CASE([$host/$ac_cv_cc_name],
[powerpc64le-*-linux-gnu/clang], [PY_SUPPORT_TIER=3], dnl Linux on PPC64 little endian, glibc, clang
[s390x-*-linux-gnu/gcc], [PY_SUPPORT_TIER=3], dnl Linux on 64bit s390x (big endian), glibc, gcc
[x86_64-*-freebsd*/clang], [PY_SUPPORT_TIER=3], dnl FreeBSD on AMD64
+ [aarch64-apple-ios*-macabi/clang], [PY_SUPPORT_TIER=3], dnl MacCatalyst on arm64
+ [x86_64-apple-ios*-macabi/clang], [PY_SUPPORT_TIER=3], dnl MacCatalyst on x86_64
[aarch64-apple-ios*-simulator/clang], [PY_SUPPORT_TIER=3], dnl iOS Simulator on arm64
[aarch64-apple-ios*/clang], [PY_SUPPORT_TIER=3], dnl iOS on ARM64
[aarch64-apple-tvos*-simulator/clang], [PY_SUPPORT_TIER=3], dnl tvOS Simulator on arm64
@@ -7932,13 +8007,17 @@ AS_CASE([$ac_sys_system],
dnl curses and tkinter user interface are not available.
dnl gdbm and nis aren't available
dnl Stub implementations are provided for pwd, grp etc APIs
+ dnl subprocess is however supported for Mac Catalyst
+ case "$_host_device" in
+ macabi) ;;
+ *) PY_STDLIB_MOD_SET_NA([_posixsubprocess]) ;;
+ esac
PY_STDLIB_MOD_SET_NA(
[_curses],
[_curses_panel],
[_gdbm],
[_multiprocessing],
[_posixshmem],
- [_posixsubprocess],
[_scproxy],
[_tkinter],
[grp],
diff --git a/iOS/testbed/Python.xcframework/Info.plist b/iOS/testbed/Python.xcframework/Info.plist
index c6418de6e74..7b32df19ab4 100644
--- a/iOS/testbed/Python.xcframework/Info.plist
+++ b/iOS/testbed/Python.xcframework/Info.plist
@@ -4,6 +4,23 @@
<dict>
<key>AvailableLibraries</key>
<array>
+ <dict>
+ <key>BinaryPath</key>
+ <string>Python.framework/Versions/Latest/Python</string>
+ <key>LibraryIdentifier</key>
+ <string>ios-arm64_x86_64-maccatalyst</string>
+ <key>LibraryPath</key>
+ <string>python.framework</string>
+ <key>SupportedArchitectures</key>
+ <array>
+ <string>x86_64</string>
+ <string>arm64</string>
+ </array>
+ <key>SupportedPlatform</key>
+ <string>ios</string>
+ <key>SupportedPlatformVariant</key>
+ <string>maccatalyst</string>
+ </dict>
<dict>
<key>BinaryPath</key>
<string>Python.framework/Python</string>
diff --git a/iOS/testbed/Python.xcframework/ios-arm64_x86_64-maccatalyst/README b/iOS/testbed/Python.xcframework/ios-arm64_x86_64-maccatalyst/README
new file mode 100644
index 00000000000..b39f40980bc
--- /dev/null
+++ b/iOS/testbed/Python.xcframework/ios-arm64_x86_64-maccatalyst/README
@@ -0,0 +1,4 @@
+This directory is intentionally empty.
+
+It is a placeholder slice for the XCFramework on Mac Catalyst,
+to install or copy your built framework to.
diff --git a/iOS/testbed/__main__.py b/iOS/testbed/__main__.py
index 1146bf3b988..1c42b07aebd 100644
--- a/iOS/testbed/__main__.py
+++ b/iOS/testbed/__main__.py
@@ -28,6 +28,15 @@
r"\s+\(Python\)\s" # Logger name
)
+# Prefix: 2025-04-27 21:43:38.530606-0500 iOSTestbed[96892:48053672]
+CATALYST_LOG_PREFIX_REGEX = re.compile(
+ r"^\d{4}-\d{2}-\d{2}" # YYYY-MM-DD
+ r"\s+\d{2}:\d{2}:\d{2}\.\d{6}" # HH:MM:SS.ssssss (microseconds, 6 digits)
+ r"[-+]\d{4}" # Timezone offset like -0500
+ r"\s+iOSTestbed\[\d+:\d+\] " # iOSTestbed[ProcessID:ThreadID] (both numbers), then a space
+)
+
+
# Work around a bug involving sys.exit and TaskGroups
# (https://github.com/python/cpython/issues/101515).
@@ -243,9 +252,13 @@ async def log_stream_task(initial_devices, lock):
sys.stdout.flush()
-async def xcode_test(location, simulator, verbose):
+async def xcode_test(location, simulator, verbose, catalyst):
# Run the test suite on the named simulator
print("Starting xcodebuild...", flush=True)
+ if catalyst:
+ destination_arg = "platform=macOS,variant=Mac Catalyst"
+ else:
+ destination_arg = f"platform=iOS Simulator,name={simulator}";
args = [
"xcodebuild",
"test",
@@ -254,13 +267,13 @@ async def xcode_test(location, simulator, verbose):
"-scheme",
"iOSTestbed",
"-destination",
- f"platform=iOS Simulator,name={simulator}",
+ destination_arg,
"-resultBundlePath",
str(location / f"{datetime.now():%Y%m%d-%H%M%S}.xcresult"),
"-derivedDataPath",
str(location / "DerivedData"),
]
- if not verbose:
+ if not verbose and not catalyst:
args += ["-quiet"]
async with async_process(
@@ -269,8 +282,16 @@ async def xcode_test(location, simulator, verbose):
stderr=subprocess.STDOUT,
) as process:
while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
- sys.stdout.write(line)
- sys.stdout.flush()
+ # For Mac Catalyst, the *actual* logs are streamed here. Only stream
+ # things that does NOT come from the process when verbose.
+ if catalyst:
+ if CATALYST_LOG_PREFIX_REGEX.match(line) or verbose:
+ line = CATALYST_LOG_PREFIX_REGEX.sub("", line)
+ sys.stdout.write(line)
+ sys.stdout.flush()
+ else:
+ sys.stdout.write(line)
+ sys.stdout.flush()
status = await asyncio.wait_for(process.wait(), timeout=1)
exit(status)
@@ -281,20 +302,31 @@ def clone_testbed(
target: Path,
framework: Path,
apps: list[Path],
+ catalyst: bool,
) -> None:
if target.exists():
print(f"{target} already exists; aborting without creating project.")
sys.exit(10)
if framework is None:
- if not (
- source / "Python.xcframework/ios-arm64_x86_64-simulator/bin"
- ).is_dir():
- print(
- f"The testbed being cloned ({source}) does not contain "
- f"a simulator framework. Re-run with --framework"
- )
- sys.exit(11)
+ if catalyst:
+ if not (
+ source / "Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework/Versions"
+ ).is_dir():
+ print(
+ f"The testbed being cloned ({source}) does not contain "
+ f"a Mac Catalyst framework. Re-run with --framework"
+ )
+ sys.exit(11)
+ else:
+ if not (
+ source / "Python.xcframework/ios-arm64_x86_64-simulator/bin"
+ ).is_dir():
+ print(
+ f"The testbed being cloned ({source}) does not contain "
+ f"a simulator framework. Re-run with --framework"
+ )
+ sys.exit(11)
else:
if not framework.is_dir():
print(f"{framework} does not exist.")
@@ -305,7 +337,7 @@ def clone_testbed(
):
print(
f"{framework} is not an XCframework, "
- f"or a simulator slice of a framework build."
+ f"or a simulator / Catalyst slice of a framework build."
)
sys.exit(13)
@@ -315,7 +347,10 @@ def clone_testbed(
print(" done")
xc_framework_path = target / "Python.xcframework"
- sim_framework_path = xc_framework_path / "ios-arm64_x86_64-simulator"
+ if catalyst:
+ sim_framework_path = xc_framework_path / "ios-arm64_x86_64-maccatalyst"
+ else:
+ sim_framework_path = xc_framework_path / "ios-arm64_x86_64-simulator"
if framework is not None:
if framework.suffix == ".xcframework":
print(" Installing XCFramework...", end="", flush=True)
@@ -328,7 +363,7 @@ def clone_testbed(
)
print(" done")
else:
- print(" Installing simulator framework...", end="", flush=True)
+ print(" Installing simulator/catalyst framework...", end="", flush=True)
if sim_framework_path.is_dir():
shutil.rmtree(sim_framework_path)
else:
@@ -360,7 +395,7 @@ def clone_testbed(
sim_framework_path.is_symlink()
and not sim_framework_path.readlink().is_absolute()
):
- print(" Rewriting symlink to simulator framework...", end="", flush=True)
+ print(" Rewriting symlink to simulator/catalyst framework...", end="", flush=True)
# Simulator framework is a relative symlink. Rewrite the symlink
# relative to the new location.
orig_sim_framework_path = (
@@ -401,42 +436,52 @@ def update_plist(testbed_path, args):
plistlib.dump(info, f)
-async def run_testbed(simulator: str | None, args: list[str], verbose: bool=False):
+async def run_testbed(simulator: str | None, args: list[str], catalyst: bool, verbose: bool=False):
location = Path(__file__).parent
print("Updating plist...", end="", flush=True)
update_plist(location, args)
print(" done.", flush=True)
- if simulator is None:
- simulator = await select_simulator_device()
- print(f"Running test on {simulator}", flush=True)
-
- # We need to get an exclusive lock on simulator creation, to avoid issues
- # with multiple simulators starting and being unable to tell which
- # simulator is due to which testbed instance. See
- # https://github.com/python/cpython/issues/130294 for details. Wait up to
- # 10 minutes for a simulator to boot.
- print("Obtaining lock on simulator creation...", flush=True)
- simulator_lock = SimulatorLock(timeout=10*60)
- await simulator_lock.acquire()
- print("Simulator lock acquired.", flush=True)
-
- # Get the list of devices that are booted at the start of the test run.
- # The simulator started by the test suite will be detected as the new
- # entry that appears on the device list.
- initial_devices = await list_devices()
-
- try:
- async with asyncio.TaskGroup() as tg:
- tg.create_task(log_stream_task(initial_devices, simulator_lock))
- tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose))
- except* MySystemExit as e:
- raise SystemExit(*e.exceptions[0].args) from None
- except* subprocess.CalledProcessError as e:
- # Extract it from the ExceptionGroup so it can be handled by `main`.
- raise e.exceptions[0]
- finally:
- simulator_lock.release()
+ if not catalyst:
+ if simulator is None:
+ simulator = await select_simulator_device()
+ print(f"Running test on {simulator}", flush=True)
+
+ # We need to get an exclusive lock on simulator creation, to avoid issues
+ # with multiple simulators starting and being unable to tell which
+ # simulator is due to which testbed instance. See
+ # https://github.com/python/cpython/issues/130294 for details. Wait up to
+ # 10 minutes for a simulator to boot.
+ print("Obtaining lock on simulator creation...", flush=True)
+ simulator_lock = SimulatorLock(timeout=10*60)
+ await simulator_lock.acquire()
+ print("Simulator lock acquired.", flush=True)
+
+ # Get the list of devices that are booted at the start of the test run.
+ # The simulator started by the test suite will be detected as the new
+ # entry that appears on the device list.
+ initial_devices = await list_devices()
+
+ try:
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(log_stream_task(initial_devices, simulator_lock))
+ tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose, catalyst=False))
+ except* MySystemExit as e:
+ raise SystemExit(*e.exceptions[0].args) from None
+ except* subprocess.CalledProcessError as e:
+ # Extract it from the ExceptionGroup so it can be handled by `main`.
+ raise e.exceptions[0]
+ finally:
+ simulator_lock.release()
+ else:
+ try:
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(xcode_test(location, simulator="", verbose=verbose, catalyst=True))
+ except* MySystemExit as e:
+ raise SystemExit(*e.exceptions[0].args) from None
+ except* subprocess.CalledProcessError as e:
+ # Extract it from the ExceptionGroup so it can be handled by `main`.
+ raise e.exceptions[0]
def main():
@@ -448,6 +493,12 @@ def main():
subcommands = parser.add_subparsers(dest="subcommand")
+ parser.add_argument(
+ "--catalyst",
+ action="store_true",
+ help="Run or clone the testbed for a Mac Catalyst build.",
+ )
+
clone = subcommands.add_parser(
"clone",
description=(
@@ -514,11 +565,16 @@ def main():
target=Path(context.location).resolve(),
framework=Path(context.framework).resolve() if context.framework else None,
apps=[Path(app) for app in context.apps],
+ catalyst = context.catalyst
)
elif context.subcommand == "run":
if test_args:
+ if context.catalyst:
+ expected_location = "Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework"
+ else:
+ expected_location = "Python.xcframework/ios-arm64_x86_64-simulator/bin"
if not (
- Path(__file__).parent / "Python.xcframework/ios-arm64_x86_64-simulator/bin"
+ Path(__file__).parent / expected_location
).is_dir():
print(
f"Testbed does not contain a compiled iOS framework. Use "
@@ -532,6 +588,7 @@ def main():
simulator=context.simulator,
verbose=context.verbose,
args=test_args,
+ catalyst=context.catalyst
)
)
else:
diff --git a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj
index c7d63909ee2..ace08f7efd9 100644
--- a/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj
+++ b/iOS/testbed/iOSTestbed.xcodeproj/project.pbxproj
@@ -70,6 +70,7 @@
607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "iOSTestbed-Info.plist"; sourceTree = "<group>"; };
608619532CB77BA900F46182 /* app_packages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app_packages; sourceTree = "<group>"; };
608619552CB7819B00F46182 /* app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = app; sourceTree = "<group>"; };
+ EE325B2A2DBE97CD000142D0 /* iOSTestbed.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iOSTestbed.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -115,6 +116,7 @@
607A66142B0EFA380010BFC8 /* iOSTestbed */ = {
isa = PBXGroup;
children = (
+ EE325B2A2DBE97CD000142D0 /* iOSTestbed.entitlements */,
608619552CB7819B00F46182 /* app */,
608619532CB77BA900F46182 /* app_packages */,
607A66592B0F08600010BFC8 /* iOSTestbed-Info.plist */,
@@ -262,7 +264,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "set -e\n\nmkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelse\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nfi\n";
+ shellScript = "set -e\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-iphonesimulator\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Simulator\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-simulator/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\" \nelif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n mkdir -p \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\"\n echo \"Installing Python modules for Mac Catalyst\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64_x86_64-maccatalyst/Python.framework/Versions/3.14/lib/\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/\"\nelse\n mkdir -p \"$CODESIGNING_FOLDER_PATH/python/lib\"\n echo \"Installing Python modules for iOS Device\"\n rsync -au --delete \"$PROJECT_DIR/Python.xcframework/ios-arm64/lib/\" \"$CODESIGNING_FOLDER_PATH/python/lib/\"\nfi\n";
showEnvVarsInLog = 0;
};
607A66562B0F06200010BFC8 /* Prepare Python Binary Modules */ = {
@@ -282,7 +284,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nPYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\necho \"Install Python $PYTHON_VER standard library extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\ndone\necho \"Install app package extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\ndone\necho \"Install app extension modules...\"\nfind \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\ndone\n\n# Clean up dylib template \nrm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\necho \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\nfind \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \n";
+ shellScript = "set -e\n\ninstall_dylib () {\n INSTALL_BASE=$1\n FULL_EXT=$2\n\n # The name of the extension file\n EXT=$(basename \"$FULL_EXT\")\n # The location of the extension file, relative to the bundle\n RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/} \n # The path to the extension file, relative to the install base\n PYTHON_EXT=${RELATIVE_EXT/$INSTALL_BASE/}\n # The full dotted name of the extension module, constructed from the file path.\n FULL_MODULE_NAME=$(echo $PYTHON_EXT | cut -d \".\" -f 1 | tr \"/\" \".\"); \n # A bundle identifier; not actually used, but required by Xcode framework packaging\n FRAMEWORK_BUNDLE_ID=$(echo $PRODUCT_BUNDLE_IDENTIFIER.$FULL_MODULE_NAME | tr \"_\" \"-\")\n # The name of the framework folder.\n FRAMEWORK_FOLDER=\"Frameworks/$FULL_MODULE_NAME.framework\"\n\n # If the framework folder doesn't exist, create it.\n if [ ! -d \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\" ]; then\n echo \"Creating framework for $RELATIVE_EXT\" \n mkdir -p \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER\"\n cp \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleExecutable -string \"$FULL_MODULE_NAME\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n plutil -replace CFBundleIdentifier -string \"$FRAMEWORK_BUNDLE_ID\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/Info.plist\"\n fi\n \n echo \"Installing binary for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" \n mv \"$FULL_EXT\" \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\"\n # Create a placeholder .fwork file where the .so was\n echo \"$FRAMEWORK_FOLDER/$FULL_MODULE_NAME\" > ${FULL_EXT%.so}.fwork\n # Create a back reference to the .so file location in the framework\n echo \"${RELATIVE_EXT%.so}.fwork\" > \"$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin\" \n}\n\nif [ \"$EFFECTIVE_PLATFORM_NAME\" = \"-maccatalyst\" ]; then\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib\")\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app_packages\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n find \"$CODESIGNING_FOLDER_PATH/Contents/Resources/app\" -name \"*.so\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \\;\n \nelse\n PYTHON_VER=$(ls -1 \"$CODESIGNING_FOLDER_PATH/python/lib\")\n echo \"Install Python $PYTHON_VER standard library extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/python/lib/$PYTHON_VER/lib-dynload\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib python/lib/$PYTHON_VER/lib-dynload/ \"$FULL_EXT\"\n done\n echo \"Install app package extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app_packages\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app_packages/ \"$FULL_EXT\"\n done\n echo \"Install app extension modules...\"\n find \"$CODESIGNING_FOLDER_PATH/app\" -name \"*.so\" | while read FULL_EXT; do\n install_dylib app/ \"$FULL_EXT\"\n done\n\n # Clean up dylib template \n rm -f \"$CODESIGNING_FOLDER_PATH/dylib-Info-template.plist\"\n echo \"Signing frameworks as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)...\"\n find \"$CODESIGNING_FOLDER_PATH/Frameworks\" -name \"*.framework\" -exec /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der \"{}\" \\; \nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@@ -362,6 +364,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_HARDENED_RUNTIME = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -381,6 +384,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -423,6 +427,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -436,6 +441,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@@ -449,9 +455,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_ENTITLEMENTS = iOSTestbed/iOSTestbed.entitlements;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
+ ENABLE_HARDENED_RUNTIME = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\"";
INFOPLIST_FILE = "iOSTestbed/iOSTestbed-Info.plist";
@@ -468,6 +477,9 @@
MARKETING_VERSION = 3.13.0a1;
PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+ SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -479,9 +491,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ CODE_SIGN_ENTITLEMENTS = iOSTestbed/iOSTestbed.entitlements;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
+ ENABLE_HARDENED_RUNTIME = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\"";
@@ -499,6 +514,9 @@
MARKETING_VERSION = 3.13.0a1;
PRODUCT_BUNDLE_IDENTIFIER = org.python.iOSTestbed;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+ SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -509,9 +527,10 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 3HEZE76D99;
+ DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\"";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
@@ -529,9 +548,10 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 3HEZE76D99;
+ DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/Python.framework/Headers\"";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
diff --git a/iOS/testbed/iOSTestbed/iOSTestbed.entitlements b/iOS/testbed/iOSTestbed/iOSTestbed.entitlements
new file mode 100644
index 00000000000..8cc185af8d7
--- /dev/null
+++ b/iOS/testbed/iOSTestbed/iOSTestbed.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+</dict>
+</plist> |

Refs #7 and #5, with #7 being the messed-up version of this patch. This is still draft. Part of beeware/Python-Apple-support#117